<?php
/**
 * @Author: laoweizhen <1149243551@qq.com>,
 * @Date: 2022/10/06 17:48,
 * @LastEditTime: 2022/10/06 17:48
 */
declare(strict_types=1);

namespace Zhen\HyperfKit;

use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Response;
use Psr\Http\Message\ResponseInterface;
use Swoole\Http\Status as StatusCode;
use Zhen\HyperfKit\Constants\ResponseCode;
use Zhen\HyperfKit\Helper\LoginUser;

class CoreResponse extends Response
{
    /**
     * 代码成功响应.
     * @param array|object $data 响应数据
     * @param string|null $msg
     * @return ResponseInterface
     * @author lwz
     */
    public function success(array|object $data = [], ?string $msg = null, array $extData = []): ResponseInterface
    {
        return $this->handleResponseJson(ResponseCode::SUCCESS, $data, $msg ?? '成功', StatusCode::OK, $extData);
    }

    /**
     * dev 环境的错误信息
     * @param \Throwable $throwable
     * @return ResponseInterface
     * @author lwz
     */
    public function debug(\Throwable $throwable): ResponseInterface
    {
        return $this->handleResponseJson(
            ResponseCode::SERVER_ERROR,
            [],
            $throwable->getMessage(),
            StatusCode::OK,
            [
                'file' => $throwable->getFile(),
                'line' => $throwable->getLine(),
                'trace' => $throwable->getTraceAsString(),
            ]
        );
    }

    /**
     * 代码异常
     * @param string|null $message
     * @param int|null $code 业务代码
     * @param array $data
     * @return ResponseInterface
     * @author lwz
     */
    public function error(?string $message = null, ?int $code = null, array $data = []): ResponseInterface
    {
        return $this->handleResponseJson($code ?? ResponseCode::SERVER_ERROR, $data, $message, StatusCode::INTERNAL_SERVER_ERROR);
    }

    /**
     * 表单错误响应.
     * @param string|null $message
     * @return ResponseInterface
     * @author lwz
     */
    public function validateError(?string $message = null): ResponseInterface
    {
        return $this->handleResponseJson(ResponseCode::VALIDATE_FAILED, [], $message);
    }

    /**
     * token 错误（过期、无效等）
     * @param string|null $message
     * @return ResponseInterface
     * @author lwz
     */
    public function tokenError(?string $message): ResponseInterface
    {
        return $this->handleResponseJson(ResponseCode::TOKEN_EXPIRED, [], $message, StatusCode::UNAUTHORIZED);
    }

    /**
     * 无权限访问
     * @param string|null $message
     * @return ResponseInterface
     * @author lwz
     */
    public function noPermission(?string $message = null): ResponseInterface
    {
        return $this->handleResponseJson(ResponseCode::NO_PERMISSION, [], $message, StatusCode::FORBIDDEN);
    }

    /**
     * 向浏览器输出图片.
     * @param string $image 图片二进制字符串
     */
    public function responseImage(string $image, string $type = 'image/png'): ResponseInterface
    {
        return $this->getResponse()
            ->withAddedHeader('content-type', $type)
            ->withBody(new SwooleStream($image));
    }

    /**
     * 格式化响应数据.
     * @param int $code
     * @param array|object $data 数据
     * @param string|null $message 描述信息
     * @param int $httpStatusCode 状态码
     * @param array $extData 扩展字段
     * @return ResponseInterface
     * @author lwz
     */
    public function handleResponseJson(int $code, array|object $data = [], ?string $message = null, int $httpStatusCode = StatusCode::OK, array $extData = []): ResponseInterface
    {
        $data = array_merge([
            'code' => $code,
            'msg' => ($message ?: ResponseCode::getMessage($code)) ?: '系统繁忙，请稍后再试。',
            'data' => $data,
        ], $extData);

        $format = $this->toJson($data);
        $response = $this->getResponse()
            ->withStatus($httpStatusCode)
            ->withAddedHeader('content-type', 'application/json; charset=utf-8')
            ->withBody(new SwooleStream($format));

        if ($refreshToken = LoginUser::getRefreshToken()) {
            $response =  $response->withHeader('Authorization', $refreshToken);
        }

        return $response;
    }
}